#include <stdio.h>
#include <cuda_runtime.h>

// CUDA kernel function
__global__ void hello_world_kernel() {
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    printf("Hello World from thread %d!\n", idx);
}

int main() {
    // Number of threads in each thread block
    int threadsPerBlock = 256;

    // Number of thread blocks in the grid
    int blocksInGrid = 30;

    // Launch the kernel
    hello_world_kernel<<<blocksInGrid, threadsPerBlock>>>();

    // Wait for GPU to finish before accessing on host
    cudaDeviceSynchronize();

    // Check for any errors launching the kernel
    cudaError_t cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "hello_world_kernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        return 1;
    }

    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
        return 1;
    }

    return 0;
}
